package v3.object.command;

import java.text.DecimalFormat;
import java.util.Map;

import v3.object.STcfg;
import v3.object.command.list.Shield;
import v3.object.command.servoCommand.ComputerMessage;
import v3.object.ship.Ship;
import v3.object.space.Universe;

public abstract class aCommand implements iCommand
{

	protected DecimalFormat format_decimal = new DecimalFormat("###,###.##");
	protected DecimalFormat format_00 = new DecimalFormat("##.##");
	protected DecimalFormat format_000 = new DecimalFormat("000");
	protected String commandName = "- NOT DEFINED -";
	Map<iCommand, String> commandNameMap;

	public aCommand()
	{
	}

	protected boolean checkEnergyRequirements(double e, Ship ship)
	{
		return e <= ship.energy;
	}

	@Override
	public boolean execute(STcfg cfg, Universe universe, Ship ship, Map<String, iCommand> commands, String[] input)
	{
		double oldStardate = universe.starDate;
		try
		{
			checkInput(input);
		}
		catch (Exception e1)
		{
			iCommand c = new ComputerMessage("COMMAND HAS WRONG PARAMETERS");
			c.execute(cfg, universe, ship, commands, input);
			return false;
		}
		
		if(!isCommandAccetable(cfg, universe, ship, commands, input))
		{
			iCommand c = new ComputerMessage("COMMAND ABORTED");
			c.execute(cfg, universe, ship, commands, input);			
			return false;
		}

		double t = calculateTime(cfg, universe, ship, commands, input);
		double e = calculateEnergy(cfg, universe, ship, commands, input);
		
		if(ship.isShieldON())
		{
			e = e + ship.getEnergyConsume(new Shield().getClass())*t;
		}

		if (!checkEnergyRequirements(e, ship))
		{
			String shield="";
			if(ship.isShieldON())
				shield="\nShield are ON";
				
			iCommand msg = new ComputerMessage(commandName, " ABORTED - not enough Energy ["+format_decimal.format(e)+" requirred ] on the ship",shield);
			msg.execute(cfg, universe, ship, commands, input);
			return false;
		}
		
		if(!confirmCommand(cfg, universe, ship, commands, input))
		{
			iCommand msg = new ComputerMessage(commandName, " CANCELLED as requests");
			msg.execute(cfg, universe, ship, commands, input);
			return false;
		}
		
		ship.energyUpdate(e);
		universe.updateStardate(t);
		boolean result = realExecute(cfg, universe, ship, commands, input);
		
		double acutalStardate = universe.starDate;
		double elapsedTime = acutalStardate-oldStardate;
		if(cfg.isVerbose())
		{
			System.out.println(" -- elapsedTime ["+commandName+"] = "+elapsedTime);
		}
		if(ship.isREDallert())
		{
			if(elapsedTime>0)
			{
				int enemyActions = (int) (elapsedTime*10+.5);
				for(int i=0;i<enemyActions;i++)
				{
//					EnemyMove enemyAction = new EnemyMove(cfg, universe, ship, commands, input);
//					enemyAction.execute();
				}
			}
		}
		else
		{
			if(elapsedTime>1)
			{
				int enemyActions = (int) (elapsedTime+.5);
				for(int i=0;i<enemyActions;i++)
				{
//					EnemyMove enemyAction = new EnemyMove(cfg, universe, ship, commands, input);
//					enemyAction.execute();
				}
			}
		}
		return result;
	}

	protected abstract boolean isCommandAccetable(STcfg cfg, Universe universe, Ship ship, Map<String, iCommand> commands, String[] input);
	protected abstract double calculateEnergy(STcfg cfg, Universe universe, Ship ship, Map<String, iCommand> commands, String[] input);
	protected abstract double calculateTime(STcfg cfg, Universe universe, Ship ship, Map<String, iCommand> commands, String[] input);
	protected abstract void checkInput(String[] input) throws Exception;
	protected abstract boolean realExecute(STcfg cfg, Universe universe, Ship ship, Map<String, iCommand> commands, String[] input);
	protected abstract boolean confirmCommand(STcfg cfg, Universe universe, Ship ship, Map<String, iCommand> commands, String[] input);
}
